﻿namespace Webinator.Impls
{
    using System;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Threading;
    using Toolboxes;

    /// <summary>
    /// Common core routines.
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed. Suppression is OK here.")]
    public class CoreCommon
    {
        private const int DefaultPollRate = 250;

        public static void SafeAction(object element, Action action)
        {
            if (element == null)
            {
                throw new Exception("Element is null");
            }

            try
            {
                action();
            }
            catch
            {
                /* ignore error, element isn't null, and this is most likely a webdriver inconsistency    
                 * I know, I know, a catch-all is bad practice.  Get over it.
                 */
            }
        }

        public static T SafeAction<T>(object element, Func<T> action)
        {
            if (element == null)
            {
                throw new Exception("Element is null");
            }

            T result = default(T);
            try
            {
                result = action();
            }
            catch
            {
                /* ignore error, element isn't null, and this is most likely a webdriver inconsistency    
                 * I know, I know, a catch-all is bad practice.  Get over it.
                 */
            }

            return result;
        }

        public bool HtmlContainsXpath(string xpath, string source)
        {
            var nodes = XPathToolbox.GetNodes(source, xpath);

            var found = true;
            if (nodes == null)
            {
                found = false;
            }
            else if (nodes.Count == 0)
            {
                found = false;
            }

            return found;
        }
        
        public bool QuickWait(Locator locator, int waitInMilliseconds, bool desiredState, Func<string> func)
        {
            var compiledXpath = XPathToolbox.GetXpathFromLocator(locator);
            var y = waitInMilliseconds / DefaultPollRate;
            var found = false;
            var sw = new Stopwatch();
            sw.Start();

            for (var x = 0; x < y; x++)
            {
                if (sw.ElapsedMilliseconds > waitInMilliseconds)
                {
                    return false;
                }

                try
                {
                    found = HtmlContainsXpath(compiledXpath, func());
                    if (found == desiredState)
                    {
                        return true;
                    }
                }
                catch
                {
                }

                Thread.Sleep(DefaultPollRate);
            }

            return found;
        }
    }
}